import React, {useState} from 'react';
import {flushSync} from 'react-dom';

// 在更新队列中，多个修改状态方法统一批处理的时候，我们期望下一个方法执行的时候，可以获取上一个方法已经处理好的值；=>函数式更新
export default function Demo() {
    let [num, setNum] = useState(10);
    const handler = () => {
        for(let i = 0; i < 10; i++) {
            // setNum(i + 1); // 最终循环出来是11。因为每次setNum的时候num还没更新。取得都是10
            setNum(num => {
                return num + 1;
            });
        }
    }
    return <div>
        <span>{num}</span>
        <button onClick={handler}>处理</button>
    </div>
}

/**
 * 函数组件中修改状态的方法和类组件中setState类似
 * react 18
 *  建立了更新队列，实现批处理（修改状态的方法是异步操作的）
 * react 16
 *  出现合成事件、周期函数中的状态更新，使用二点是更新队列和批处理
 *  但是出现在其他异步操作中，更新状态的方法是同步处理的
 */
export default function Demo() {
    console.log('render');
    let [x, setX] = useState(10);
    let [y, setY] = useState(20);
    const handler = () => {
        setTimeout(() => {
            setX(x + 1);
            setY(y + 1);
        }, 1000);
    }
    return <div>
        <span>{x}</span>
        <span>{y}</span>
        <button onClick={handler}>处理</button>
    </div>
}

// 惰性初始state
export default function Demo(props) {
    let { x, y } = props,
        initial = x + y; // 每次render都会重新执行这段代码，不优雅。可以给useState传个函数
    // const [num, setNum] = useState(initial);
    const [num, setNum] = useState(() => {
        return props.x + props.y;
    });
    const handler = () => {
        setNum(num + 1);
    };
    return <div>
        <span>{num}</span>
        <button onClick={handler}>处理</button>
    </div>
}

// 内部性能优化
// 初始值是10，修改成10，值没有改变，不会触发render。函数根本不是重新执行，而不是执行了做dom对比。跟class组件不一样，pureComponet处理。

export default function Demo() {
    // 默认情况下，基于useState返回的修改状态的方法，不像类组件中的this.setState一样。不支持部分状态更改。
    // setState({
    //     ...state,
    //     x: 1,
    // })
    let [x, setX] = useState(10);
    let [y, setY] = useState(20);
    const handler = () => {
        setX(11);
        flushSync(() => {
            setX(x + 1);
        })
        setY(22);
        // 两次set只执行一次render。把任务放到队列里边。最后统一执行。如果让每次更新都render，执行一次flushSync()。强制刷新队列。
    }
    return <div>
        <span>{x}</span>
        <span>{y}</span>
        <button onClick={handler}>处理</button>
    </div>
}